Reversing - Kreker_V2.exe

:: cracking, reverse engineering

In this article we’ll look at another crackme. This one was pretty difficult and has a bunch of cool stuff in it, including the injection and execution of obfsucated code into another process.

Crackme

The crackme in question is this one, so stop reading now if you want to give it a go yourself!

The crackme asks you to find the serial and / or patch the program.

Initial analysis shows a C++ console program that asks for a password on the command line. It then displays a message box with the text “Lose!!”.

First Impressions

With a bit of digging it is fairly easy to find the location where cin is being called. It reads numeric characters and stores the result at the hardcoded memory address of 406410. Looking at the imported symbols at this point yields the following (well, some of it):

There are some potentially interesting functions imported from kernel32.dll, perhaps used for some anti-debugging. We can also find the call that shows the message box fairly easily:

We can see that the message box string pointer is hardcoded to 406408, and indeed pausing execution whilst looking at the memory shows the “Lose!!” text. Looking around at the surrounding code doesn’t yield any obvious serial checks. Although both the message box string address and the user’s input address are hardcoded, a search for code accessing either of those memory locations comes up with nothing. Instead, we can try to set a hardware breakpoint on those bits of memory to trigger when they are written to or read from, hopefully leading us to somewhere related to the serial checking.

Unfortunately, the hardware breakpoints do not seem to trigger anything! There are a few techniques to deal with hardware breakpoints, and looking at the special registers DR0–7 we can see the breakpoint is still in there - it seems the program is not detecting and removing them…

The Mystery Continues

Let’s have a look at the first part of the function that is called after the password is entered:

It seems to be loading lots of big hardcoded numbers into the floating point registers (xmm), copying them onto the stack and then looping around XORing them with stuff. XORing things is often a sign of decryption, so if we let the first loops run and then look at the stack in the memory dump we will see something interesting revealed …

“kernel32.dll” and “GetProcessId” strings - the name of a win32 library and function. Presumably the program is going to try and use this string with GetProcAddress and then call it. The strings are passed to a function that is a bit long to show here, but it does NOT use GetProcAddress! Instead, it implements its own version of it.

First, it discovers the base module address of kernel32.dll. It does this by navigating through the Thread Information Block, always stored at fs:[0]. From there, it navigates to the Process Information Block, then the Loader Data, and finally to a doubly linked list InMemoryOrderModule. The third entry in here is always kernel32.dll. Here’s the code, annotated for your viewing pleasure:

Now it has a handle to the base of the module, it can locate and search the module’s function export table to locate a given function. It is too much code to show here, but essentially there is a function that:

  • Takes a library name and function name
  • Takes arguments for the function
  • Finds the kernel32.dll base module handle (as above)
  • Walks the export table to find LoadLibraryW in kernel32.dll
  • Calls LoadLibraryW with the passed library name (even if it is also kernel32.dll)
  • Walks the export table of the returned module to find the passed function name
  • Calls the function with the given arguments

This is quite a sneaky piece of code since it avoids most of the normal methods of detecting libraries and functions that are dynamically loaded.

With all this in place, the original piece of decrypted data was trying to call GetProcessId. It mysteriously hangs onto this id for quite some time whilst it busily decrypts a whole bunch more stuff. This time it is not a string - it looks more like opcode data - but we’ll come back to that shortly. It writes the retrieved process id into a particular location within the decrypted data.

The dynamic execute function is then used to do a bunch more stuff:

  • Calls SHGetSpecialFolderPath in Shell32.dll, returning c:\windows\syswow64
  • Calls CreateProcess appending notepad.exe to the above system path
  • Calls VirtualAllocEx, creating some heap memory in the new notepad process
  • Calls WriteProcessMemory, copying a block of data into the new heap memory (more on this in a moment)
  • Some calls to GetThreadContext and SetThreadContext, causing the block of data to be executed
  • Some cleanup code, closing handles

The Injected Data

Let’s have a look at the block of data that is copied into notepad.exe and executed. It is a simple matter to pause before the function is executed and note the start address and length parameters of the data to be copied

Here we can see the location of the data is 19FB68 of 340 length.

If we view this in the disassembler we will see a decrypted program appear. It is a bit too long to list here, in essence it has some machinery similar to the parent program that allows it to locate kernel32.dll and find functions by their names. It calls a bunch of functions, which are dynamically executed much like in the parent process. In particular, they are:

  • OpenProcess
  • ReadProcessMemory
  • WriteProcessMemory
  • ExitProcess

Can you guess what it does? The process id from the parent earlier was written into this program. It opens the parent process, and reads the area of memory where the password was entered from cin. Because ReadProcessMemory is in another process, our hardware breakpoint does not trigger (I think!). It then performs a serial check and finally writes a result back to the parent process’ memory, in the location where the message box will read its text from, again not triggering our breakpoint. Let’s look at a bit of it:

Here you can see the actual serial check - it is simply the hardcoded number of 23D4!

Conclusion

This was a really cool crackme, and was pretty tough! The author put in a lot of effort in order to obfsucate a simple hardcoded serial number. Sneaky tricks abound, I particularly like the program injection and writing back into the parent’s memory.